home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / DelayLine.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-05  |  25.4 KB  |  754 lines  |  [TEXT/KAHL]

  1. /* DelayLine.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "DelayLine.h"
  31. #include "Memory.h"
  32. #include "DelayEffectSpec.h"
  33.  
  34.  
  35. /* tap algorithm select */
  36. typedef enum
  37.     {
  38.         eTapLeftToLeftNoFilter EXECUTE(= -3241),
  39.         eTapLeftToMonoNoFilter,
  40.         eTapLeftToRightNoFilter,
  41.         eTapMonoToLeftNoFilter,
  42.         eTapMonoToMonoNoFilter,
  43.         eTapMonoToRightNoFilter,
  44.         eTapRightToLeftNoFilter,
  45.         eTapRightToMonoNoFilter,
  46.         eTapRightToRightNoFilter,
  47.         eTapLeftToLeftAverageFilter,
  48.         eTapLeftToMonoAverageFilter,
  49.         eTapLeftToRightAverageFilter,
  50.         eTapMonoToLeftAverageFilter,
  51.         eTapMonoToMonoAverageFilter,
  52.         eTapMonoToRightAverageFilter,
  53.         eTapRightToLeftAverageFilter,
  54.         eTapRightToMonoAverageFilter,
  55.         eTapRightToRightAverageFilter
  56.     } TapAlgorithm;
  57.  
  58.  
  59. typedef struct DelayLineTapRec
  60.     {
  61.         /* link to next tap record */
  62.         struct DelayLineTapRec*        Next;
  63.  
  64.         /* what are we tapping */
  65.         DelayChannelType    SourceTap;
  66.         float                            SourceTime;
  67.         float                            SourceTimeAccent1Adjust;
  68.         float                            SourceTimeAccent2Adjust;
  69.         float                            SourceTimeAccent3Adjust;
  70.         float                            SourceTimeAccent4Adjust;
  71.         DelayChannelType    TargetTap;
  72.         float                            TargetTime;
  73.         float                            TargetTimeAccent1Adjust;
  74.         float                            TargetTimeAccent2Adjust;
  75.         float                            TargetTimeAccent3Adjust;
  76.         float                            TargetTimeAccent4Adjust;
  77.         float                            ScaleFactor;
  78.         float                            ScaleFactorAccent1Adjust;
  79.         float                            ScaleFactorAccent2Adjust;
  80.         float                            ScaleFactorAccent3Adjust;
  81.         float                            ScaleFactorAccent4Adjust;
  82.  
  83.         /* lowpass filter control */
  84.         DelayFilterType        EnableFilter;
  85.  
  86.         /* control information */
  87.         TapAlgorithm            TapProcessAlgorithm;
  88.  
  89.         /* state information */
  90.         long                            SourceOffset;
  91.         long                            TargetOffset;
  92.         float                            Scaling;
  93.         largefixedsigned    MovingAverageFilterState;
  94.     } DelayLineTapRec;
  95.  
  96.  
  97. struct DelayLineRec
  98.     {
  99.         /* maximum delay */
  100.         float                            MaxDelayTime;
  101.  
  102.         /* state information */
  103.         long                            DelayLineLength; /* must be power of 2 */
  104.         long                            DelayLineIndex;
  105.         largefixedsigned*    LeftDelayLineArray; /* for mono, only this one is used */
  106.         largefixedsigned*    RightDelayLineArray;
  107.         long                            FramesPerSecond;
  108.  
  109.         /* tap list */
  110.         DelayLineTapRec*    Taps;
  111.  
  112.         /* free list link */
  113.         DelayLineRec*            Next;
  114.     };
  115.  
  116.  
  117. static DelayLineRec*            DelayLineFreeList = NIL;
  118. static DelayLineTapRec*        DelayLineTapFreeList = NIL;
  119.  
  120.  
  121. /* flush cached delay line records */
  122. void                            FlushCachedDelayLineStuff(void)
  123.     {
  124.         while (DelayLineFreeList != NIL)
  125.             {
  126.                 DelayLineRec*        Temp;
  127.  
  128.                 Temp = DelayLineFreeList;
  129.                 DelayLineFreeList = DelayLineFreeList->Next;
  130.                 ReleasePtr((char*)Temp);
  131.             }
  132.         while (DelayLineTapFreeList != NIL)
  133.             {
  134.                 DelayLineTapRec*    Temp;
  135.  
  136.                 Temp = DelayLineTapFreeList;
  137.                 DelayLineTapFreeList = DelayLineTapFreeList->Next;
  138.                 ReleasePtr((char*)Temp);
  139.             }
  140.     }
  141.  
  142.  
  143. /* create a new delay line processor */
  144. DelayLineRec*            NewDelayLineProcessor(struct DelayEffectRec* Template,
  145.                                         long FramesPerSecond)
  146.     {
  147.         DelayLineRec*        Delay;
  148.         long                        Temp;
  149.         long                        Scan;
  150.         long                        Limit;
  151.         DelayLineTapRec*    Appender;
  152.  
  153.         CheckPtrExistence(Template);
  154.         if (DelayLineFreeList != NIL)
  155.             {
  156.                 Delay = DelayLineFreeList;
  157.                 DelayLineFreeList = DelayLineFreeList->Next;
  158.             }
  159.          else
  160.             {
  161.                 Delay = (DelayLineRec*)AllocPtrCanFail(sizeof(DelayLineRec),"DelayLineRec");
  162.                 if (Delay == NIL)
  163.                     {
  164.                      FailurePoint1:
  165.                         return NIL;
  166.                     }
  167.             }
  168.  
  169.         Delay->MaxDelayTime = GetDelayMaxTime(Template);
  170.         Delay->Taps = NIL;
  171.  
  172.         /* set line length */
  173.         Temp = FramesPerSecond * Delay->MaxDelayTime + 1;
  174.         Temp = Temp & 0x3fffffff;
  175.         Delay->DelayLineLength = 1UL;
  176.         while (Temp != 0)
  177.             {
  178.                 Temp = Temp >> 1;
  179.                 Delay->DelayLineLength = Delay->DelayLineLength << 1;
  180.             }
  181.         Delay->FramesPerSecond = FramesPerSecond;
  182.         Delay->DelayLineIndex = 0;
  183.  
  184.         /* build lines */
  185.         Delay->LeftDelayLineArray = (largefixedsigned*)AllocPtrCanFail(
  186.             sizeof(largefixedsigned) * Delay->DelayLineLength,"DelayLineArray");
  187.         if (Delay->LeftDelayLineArray == NIL)
  188.             {
  189.              FailurePoint2:
  190.                 ReleasePtr((char*)Delay);
  191.                 goto FailurePoint1;
  192.             }
  193.         Delay->RightDelayLineArray = (largefixedsigned*)AllocPtrCanFail(
  194.             sizeof(largefixedsigned) * Delay->DelayLineLength,"DelayLineArray");
  195.         if (Delay->RightDelayLineArray == NIL)
  196.             {
  197.              FailurePoint3:
  198.                 ReleasePtr((char*)Delay->LeftDelayLineArray);
  199.                 goto FailurePoint2;
  200.             }
  201.         for (Temp = 0; Temp < Delay->DelayLineLength; Temp += 1)
  202.             {
  203.                 Delay->LeftDelayLineArray[Temp] = 0;
  204.                 Delay->RightDelayLineArray[Temp] = 0;
  205.             }
  206.  
  207.         /* build tap list */
  208.         Appender = NIL;
  209.         Limit = GetDelayEffectSpecNumTaps(Template);
  210.         for (Scan = 0; Scan < Limit; Scan += 1)
  211.             {
  212.                 DelayLineTapRec*        Tap;
  213.  
  214.                 /* allocate delay line */
  215.                 if (DelayLineTapFreeList != NIL)
  216.                     {
  217.                         Tap = DelayLineTapFreeList;
  218.                         DelayLineTapFreeList = DelayLineTapFreeList->Next;
  219.                     }
  220.                  else
  221.                     {
  222.                         Tap = (DelayLineTapRec*)AllocPtrCanFail(sizeof(DelayLineTapRec),"DelayLineTapRec");
  223.                         if (Tap == NIL)
  224.                             {
  225.                              FailurePoint4:
  226.                                 while (Delay->Taps != NIL)
  227.                                     {
  228.                                         Tap = Delay->Taps;
  229.                                         Delay->Taps = Delay->Taps->Next;
  230.                                         ReleasePtr((char*)Tap);
  231.                                     }
  232.                                 ReleasePtr((char*)Delay->RightDelayLineArray);
  233.                                 goto FailurePoint3;
  234.                             }
  235.                     }
  236.                 /* append to list */
  237.                 Tap->Next = NIL;
  238.                 if (Appender == NIL)
  239.                     {
  240.                         Delay->Taps = Tap;
  241.                     }
  242.                  else
  243.                     {
  244.                         Appender->Next = Tap;
  245.                     }
  246.                 Appender = Tap;
  247.                 /* fill in template fields */
  248.                 Tap->SourceTap = GetDelayTapSource(Template,Scan);
  249.                 Tap->SourceTime = GetDelayTapSourceTime(Template,Scan);
  250.                 Tap->SourceTimeAccent1Adjust = GetDelayTapSourceTimeAccent1(Template,Scan);
  251.                 Tap->SourceTimeAccent2Adjust = GetDelayTapSourceTimeAccent2(Template,Scan);
  252.                 Tap->SourceTimeAccent3Adjust = GetDelayTapSourceTimeAccent3(Template,Scan);
  253.                 Tap->SourceTimeAccent4Adjust = GetDelayTapSourceTimeAccent4(Template,Scan);
  254.                 Tap->TargetTap = GetDelayTapTarget(Template,Scan);
  255.                 Tap->TargetTime = GetDelayTapTargetTime(Template,Scan);
  256.                 Tap->TargetTimeAccent1Adjust = GetDelayTapTargetTimeAccent1(Template,Scan);
  257.                 Tap->TargetTimeAccent2Adjust = GetDelayTapTargetTimeAccent2(Template,Scan);
  258.                 Tap->TargetTimeAccent3Adjust = GetDelayTapTargetTimeAccent3(Template,Scan);
  259.                 Tap->TargetTimeAccent4Adjust = GetDelayTapTargetTimeAccent4(Template,Scan);
  260.                 Tap->ScaleFactor = GetDelayTapScale(Template,Scan);
  261.                 Tap->ScaleFactorAccent1Adjust = GetDelayTapScaleAccent1(Template,Scan);
  262.                 Tap->ScaleFactorAccent2Adjust = GetDelayTapScaleAccent2(Template,Scan);
  263.                 Tap->ScaleFactorAccent3Adjust = GetDelayTapScaleAccent3(Template,Scan);
  264.                 Tap->ScaleFactorAccent4Adjust = GetDelayTapScaleAccent4(Template,Scan);
  265.                 Tap->EnableFilter = GetDelayTapFilterType(Template,Scan);
  266.                 /* initialize state variables */
  267.                 Tap->MovingAverageFilterState = 0;
  268.                 /* determine which algorithm to use */
  269.                 switch (Tap->SourceTap)
  270.                     {
  271.                         default:
  272.                             EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad tap source"));
  273.                             break;
  274.                         case eTapLeftChannel:
  275.                             switch (Tap->TargetTap)
  276.                                 {
  277.                                     default:
  278.                                         EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad tap target"));
  279.                                         break;
  280.                                     case eTapLeftChannel:
  281.                                         switch (Tap->EnableFilter)
  282.                                             {
  283.                                                 default:
  284.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  285.                                                     break;
  286.                                                 case eTapNoFilter:
  287.                                                     Tap->TapProcessAlgorithm = eTapLeftToLeftNoFilter;
  288.                                                     break;
  289.                                                 case eTapMovingAverageLP:
  290.                                                     Tap->TapProcessAlgorithm = eTapLeftToLeftAverageFilter;
  291.                                                     break;
  292.                                             }
  293.                                         break;
  294.                                     case eTapRightChannel:
  295.                                         switch (Tap->EnableFilter)
  296.                                             {
  297.                                                 default:
  298.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  299.                                                     break;
  300.                                                 case eTapNoFilter:
  301.                                                     Tap->TapProcessAlgorithm = eTapLeftToRightNoFilter;
  302.                                                     break;
  303.                                                 case eTapMovingAverageLP:
  304.                                                     Tap->TapProcessAlgorithm = eTapLeftToRightAverageFilter;
  305.                                                     break;
  306.                                             }
  307.                                         break;
  308.                                     case eTapMonoChannel:
  309.                                         switch (Tap->EnableFilter)
  310.                                             {
  311.                                                 default:
  312.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  313.                                                     break;
  314.                                                 case eTapNoFilter:
  315.                                                     Tap->TapProcessAlgorithm = eTapLeftToMonoNoFilter;
  316.                                                     break;
  317.                                                 case eTapMovingAverageLP:
  318.                                                     Tap->TapProcessAlgorithm = eTapLeftToMonoAverageFilter;
  319.                                                     break;
  320.                                             }
  321.                                         break;
  322.                                 }
  323.                             break;
  324.                         case eTapRightChannel:
  325.                             switch (Tap->TargetTap)
  326.                                 {
  327.                                     default:
  328.                                         EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad tap target"));
  329.                                         break;
  330.                                     case eTapLeftChannel:
  331.                                         switch (Tap->EnableFilter)
  332.                                             {
  333.                                                 default:
  334.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  335.                                                     break;
  336.                                                 case eTapNoFilter:
  337.                                                     Tap->TapProcessAlgorithm = eTapRightToLeftNoFilter;
  338.                                                     break;
  339.                                                 case eTapMovingAverageLP:
  340.                                                     Tap->TapProcessAlgorithm = eTapRightToLeftAverageFilter;
  341.                                                     break;
  342.                                             }
  343.                                         break;
  344.                                     case eTapRightChannel:
  345.                                         switch (Tap->EnableFilter)
  346.                                             {
  347.                                                 default:
  348.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  349.                                                     break;
  350.                                                 case eTapNoFilter:
  351.                                                     Tap->TapProcessAlgorithm = eTapRightToRightNoFilter;
  352.                                                     break;
  353.                                                 case eTapMovingAverageLP:
  354.                                                     Tap->TapProcessAlgorithm = eTapRightToRightAverageFilter;
  355.                                                     break;
  356.                                             }
  357.                                         break;
  358.                                     case eTapMonoChannel:
  359.                                         switch (Tap->EnableFilter)
  360.                                             {
  361.                                                 default:
  362.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  363.                                                     break;
  364.                                                 case eTapNoFilter:
  365.                                                     Tap->TapProcessAlgorithm = eTapRightToMonoNoFilter;
  366.                                                     break;
  367.                                                 case eTapMovingAverageLP:
  368.                                                     Tap->TapProcessAlgorithm = eTapRightToMonoAverageFilter;
  369.                                                     break;
  370.                                             }
  371.                                         break;
  372.                                 }
  373.                             break;
  374.                         case eTapMonoChannel:
  375.                             switch (Tap->TargetTap)
  376.                                 {
  377.                                     default:
  378.                                         EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad tap target"));
  379.                                         break;
  380.                                     case eTapLeftChannel:
  381.                                         switch (Tap->EnableFilter)
  382.                                             {
  383.                                                 default:
  384.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  385.                                                     break;
  386.                                                 case eTapNoFilter:
  387.                                                     Tap->TapProcessAlgorithm = eTapMonoToLeftNoFilter;
  388.                                                     break;
  389.                                                 case eTapMovingAverageLP:
  390.                                                     Tap->TapProcessAlgorithm = eTapMonoToLeftAverageFilter;
  391.                                                     break;
  392.                                             }
  393.                                         break;
  394.                                     case eTapRightChannel:
  395.                                         switch (Tap->EnableFilter)
  396.                                             {
  397.                                                 default:
  398.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  399.                                                     break;
  400.                                                 case eTapNoFilter:
  401.                                                     Tap->TapProcessAlgorithm = eTapMonoToRightNoFilter;
  402.                                                     break;
  403.                                                 case eTapMovingAverageLP:
  404.                                                     Tap->TapProcessAlgorithm = eTapMonoToRightAverageFilter;
  405.                                                     break;
  406.                                             }
  407.                                         break;
  408.                                     case eTapMonoChannel:
  409.                                         switch (Tap->EnableFilter)
  410.                                             {
  411.                                                 default:
  412.                                                     EXECUTE(PRERR(ForceAbort,"NewDelayLineProcessor:  bad filter"));
  413.                                                     break;
  414.                                                 case eTapNoFilter:
  415.                                                     Tap->TapProcessAlgorithm = eTapMonoToMonoNoFilter;
  416.                                                     break;
  417.                                                 case eTapMovingAverageLP:
  418.                                                     Tap->TapProcessAlgorithm = eTapMonoToMonoAverageFilter;
  419.                                                     break;
  420.                                             }
  421.                                         break;
  422.                                 }
  423.                             break;
  424.                     }
  425.             }
  426.  
  427.         return Delay;
  428.     }
  429.  
  430.  
  431. /* dispose of the delay line processor */
  432. void                            DisposeDelayLineProcessor(DelayLineRec* Delay)
  433.     {
  434.         CheckPtrExistence(Delay);
  435.         ReleasePtr((char*)Delay->LeftDelayLineArray);
  436.         ReleasePtr((char*)Delay->RightDelayLineArray);
  437.         while (Delay->Taps != NIL)
  438.             {
  439.                 DelayLineTapRec*        Temp;
  440.  
  441.                 Temp = Delay->Taps;
  442.                 Delay->Taps = Delay->Taps->Next;
  443.                 Temp->Next = DelayLineTapFreeList;
  444.                 DelayLineTapFreeList = Temp;
  445.             }
  446.         Delay->Next = DelayLineFreeList;
  447.         DelayLineFreeList = Delay;
  448.     }
  449.  
  450.  
  451. /* update delay line state with accent information */
  452. void                            UpdateDelayLineState(DelayLineRec* Delay, float Accent1, float Accent2,
  453.                                         float Accent3, float Accent4)
  454.     {
  455.         DelayLineTapRec*    Scan;
  456.  
  457.         CheckPtrExistence(Delay);
  458.         /* update tap states */
  459.         Scan = Delay->Taps;
  460.         while (Scan != NIL)
  461.             {
  462.                 float                            Time;
  463.  
  464.                 /* determine source offset */
  465.                 Time = Scan->SourceTime + Accent1 * Scan->SourceTimeAccent1Adjust
  466.                     + Accent2 * Scan->SourceTimeAccent2Adjust + Accent3
  467.                     * Scan->SourceTimeAccent3Adjust + Accent4 * Scan->SourceTimeAccent4Adjust;
  468.                 if (Time < 0)
  469.                     {
  470.                         Time = 0;
  471.                     }
  472.                 if (Time > Delay->MaxDelayTime)
  473.                     {
  474.                         Time = Delay->MaxDelayTime;
  475.                     }
  476.                 Scan->SourceOffset = Time * Delay->FramesPerSecond;
  477.                 /* determine target offset */
  478.                 Time = Scan->TargetTime + Accent1 * Scan->TargetTimeAccent1Adjust
  479.                     + Accent2 * Scan->TargetTimeAccent2Adjust + Accent3
  480.                     * Scan->TargetTimeAccent3Adjust + Accent4 * Scan->TargetTimeAccent4Adjust;
  481.                 if (Time < 0)
  482.                     {
  483.                         Time = 0;
  484.                     }
  485.                 if (Time > Delay->MaxDelayTime)
  486.                     {
  487.                         Time = Delay->MaxDelayTime;
  488.                     }
  489.                 Scan->TargetOffset = Time * Delay->FramesPerSecond;
  490.                 /* determine scale factor */
  491.                 Scan->Scaling = Scan->ScaleFactor + Accent1 * Scan->ScaleFactorAccent1Adjust
  492.                     + Accent2 * Scan->ScaleFactorAccent2Adjust + Accent3
  493.                     * Scan->ScaleFactorAccent3Adjust + Accent4 * Scan->ScaleFactorAccent4Adjust;
  494.                 /* do the next one */
  495.                 Scan = Scan->Next;
  496.             }
  497.     }
  498.  
  499.  
  500. /* apply delay processing to some stuff to stereo data */
  501. void                            ApplyDelayLineStereo(largefixedsigned* Data, long NumFrames,
  502.                                         DelayLineRec* Delay)
  503.     {
  504.         long                        Scan;
  505.         long                        VectorMask;
  506.         long                        VectorIndex;
  507.         largefixedsigned*    LeftDelayLineArray;
  508.         largefixedsigned*    RightDelayLineArray;
  509.  
  510.         CheckPtrExistence(Data);
  511.         CheckPtrExistence(Delay);
  512.         VectorMask = Delay->DelayLineLength - 1;
  513.         VectorIndex = Delay->DelayLineIndex;
  514.         LeftDelayLineArray = Delay->LeftDelayLineArray;
  515.         RightDelayLineArray = Delay->RightDelayLineArray;
  516.         for (Scan = 0; Scan < NumFrames; Scan += 1)
  517.             {
  518.                 DelayLineTapRec*    Tap;
  519.  
  520.                 /* initialize current point with dry data */
  521.                 LeftDelayLineArray[VectorIndex] = Data[Scan * 2 + 0];
  522.                 RightDelayLineArray[VectorIndex] = Data[Scan * 2 + 1];
  523.                 /* iterate over taps */
  524.                 Tap = Delay->Taps;
  525.                 while (Tap != NIL)
  526.                     {
  527.                         long                            SourceIndex;
  528.                         long                            TargetIndex;
  529.                         largefixedsigned    Temp;
  530.                         largefixedsigned    Temp2;
  531.  
  532.                         /* precompute some stuff */
  533.                         SourceIndex = VectorMask & (VectorIndex +  Tap->SourceOffset);
  534.                         TargetIndex = VectorMask & (VectorIndex +  Tap->TargetOffset);
  535.                         PRNGCHK(LeftDelayLineArray,&(LeftDelayLineArray[SourceIndex]),
  536.                             sizeof(LeftDelayLineArray[SourceIndex]));
  537.                         PRNGCHK(LeftDelayLineArray,&(LeftDelayLineArray[TargetIndex]),
  538.                             sizeof(LeftDelayLineArray[TargetIndex]));
  539.                         PRNGCHK(RightDelayLineArray,&(RightDelayLineArray[SourceIndex]),
  540.                             sizeof(RightDelayLineArray[SourceIndex]));
  541.                         PRNGCHK(RightDelayLineArray,&(RightDelayLineArray[TargetIndex]),
  542.                             sizeof(RightDelayLineArray[TargetIndex]));
  543.                         /* apply transformation */
  544.                         switch (Tap->TapProcessAlgorithm)
  545.                             {
  546.                                 default:
  547.                                     EXECUTE(PRERR(ForceAbort,
  548.                                         "ApplyDelayLineStereo:  unknown tap processing algorithm"));
  549.                                     break;
  550.                                 case eTapLeftToLeftNoFilter:
  551.                                     LeftDelayLineArray[TargetIndex] += (largefixedsigned)(
  552.                                         LeftDelayLineArray[SourceIndex] * Tap->Scaling);
  553.                                     break;
  554.                                 case eTapLeftToMonoNoFilter:
  555.                                     Temp = LeftDelayLineArray[SourceIndex] * Tap->Scaling;
  556.                                     LeftDelayLineArray[TargetIndex] += Temp;
  557.                                     RightDelayLineArray[TargetIndex] += Temp;
  558.                                     break;
  559.                                 case eTapLeftToRightNoFilter:
  560.                                     RightDelayLineArray[TargetIndex] += (largefixedsigned)(
  561.                                         LeftDelayLineArray[SourceIndex] * Tap->Scaling);
  562.                                     break;
  563.                                 case eTapMonoToLeftNoFilter:
  564.                                     LeftDelayLineArray[TargetIndex] += (largefixedsigned)(
  565.                                         ((LeftDelayLineArray[SourceIndex]
  566.                                         + RightDelayLineArray[SourceIndex]) >> 1) * Tap->Scaling);
  567.                                     break;
  568.                                 case eTapMonoToMonoNoFilter:
  569.                                     Temp = ((LeftDelayLineArray[SourceIndex]
  570.                                         + RightDelayLineArray[SourceIndex]) >> 1) * Tap->Scaling;
  571.                                     LeftDelayLineArray[TargetIndex] += Temp;
  572.                                     RightDelayLineArray[TargetIndex] += Temp;
  573.                                     break;
  574.                                 case eTapMonoToRightNoFilter:
  575.                                     RightDelayLineArray[TargetIndex] += (largefixedsigned)(
  576.                                         ((LeftDelayLineArray[SourceIndex]
  577.                                         + RightDelayLineArray[SourceIndex]) >> 1) * Tap->Scaling);
  578.                                     break;
  579.                                 case eTapRightToLeftNoFilter:
  580.                                     LeftDelayLineArray[TargetIndex] += (largefixedsigned)(
  581.                                         RightDelayLineArray[SourceIndex] * Tap->Scaling);
  582.                                     break;
  583.                                 case eTapRightToMonoNoFilter:
  584.                                     Temp = RightDelayLineArray[SourceIndex] * Tap->Scaling;
  585.                                     LeftDelayLineArray[TargetIndex] += Temp;
  586.                                     RightDelayLineArray[TargetIndex] += Temp;
  587.                                     break;
  588.                                 case eTapRightToRightNoFilter:
  589.                                     RightDelayLineArray[TargetIndex] += (largefixedsigned)(
  590.                                         RightDelayLineArray[SourceIndex] * Tap->Scaling);
  591.                                     break;
  592.                                 case eTapLeftToLeftAverageFilter:
  593.                                     Temp = LeftDelayLineArray[SourceIndex];
  594.                                     LeftDelayLineArray[TargetIndex] += (largefixedsigned)(((Temp
  595.                                         + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling);
  596.                                     Tap->MovingAverageFilterState = Temp;
  597.                                     break;
  598.                                 case eTapLeftToMonoAverageFilter:
  599.                                     Temp = LeftDelayLineArray[SourceIndex];
  600.                                     Temp2 = ((Temp + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling;
  601.                                     LeftDelayLineArray[TargetIndex] += Temp2;
  602.                                     RightDelayLineArray[TargetIndex] += Temp2;
  603.                                     Tap->MovingAverageFilterState = Temp;
  604.                                     break;
  605.                                 case eTapLeftToRightAverageFilter:
  606.                                     Temp = LeftDelayLineArray[SourceIndex];
  607.                                     RightDelayLineArray[TargetIndex] += (largefixedsigned)(((Temp
  608.                                         + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling);
  609.                                     Tap->MovingAverageFilterState = Temp;
  610.                                     break;
  611.                                 case eTapMonoToLeftAverageFilter:
  612.                                     Temp = (LeftDelayLineArray[SourceIndex]
  613.                                         + RightDelayLineArray[SourceIndex]) >> 1;
  614.                                     LeftDelayLineArray[TargetIndex] += (largefixedsigned)(((Temp
  615.                                         + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling);
  616.                                     Tap->MovingAverageFilterState = Temp;
  617.                                     break;
  618.                                 case eTapMonoToMonoAverageFilter:
  619.                                     Temp = (LeftDelayLineArray[SourceIndex]
  620.                                         + RightDelayLineArray[SourceIndex]) >> 1;
  621.                                     Temp2 = ((Temp + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling;
  622.                                     LeftDelayLineArray[TargetIndex] += Temp2;
  623.                                     RightDelayLineArray[TargetIndex] += Temp2;
  624.                                     Tap->MovingAverageFilterState = Temp;
  625.                                     break;
  626.                                 case eTapMonoToRightAverageFilter:
  627.                                     Temp = (LeftDelayLineArray[SourceIndex]
  628.                                         + RightDelayLineArray[SourceIndex]) >> 1;
  629.                                     RightDelayLineArray[TargetIndex] += (largefixedsigned)(((Temp
  630.                                         + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling);
  631.                                     Tap->MovingAverageFilterState = Temp;
  632.                                     break;
  633.                                 case eTapRightToLeftAverageFilter:
  634.                                     Temp = RightDelayLineArray[SourceIndex];
  635.                                     LeftDelayLineArray[TargetIndex] += (largefixedsigned)(((Temp
  636.                                         + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling);
  637.                                     Tap->MovingAverageFilterState = Temp;
  638.                                     break;
  639.                                 case eTapRightToMonoAverageFilter:
  640.                                     Temp = RightDelayLineArray[SourceIndex];
  641.                                     Temp2 = ((Temp + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling;
  642.                                     LeftDelayLineArray[TargetIndex] += Temp2;
  643.                                     RightDelayLineArray[TargetIndex] += Temp2;
  644.                                     Tap->MovingAverageFilterState = Temp;
  645.                                     break;
  646.                                 case eTapRightToRightAverageFilter:
  647.                                     Temp = RightDelayLineArray[SourceIndex];
  648.                                     RightDelayLineArray[TargetIndex] += (largefixedsigned)(((Temp
  649.                                         + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling);
  650.                                     Tap->MovingAverageFilterState = Temp;
  651.                                     break;
  652.                             }
  653.                         /* do the next one */
  654.                         Tap = Tap->Next;
  655.                     }
  656.                 /* perform data update */
  657.                 PRNGCHK(Data,&(Data[Scan * 2 + 0]),sizeof(Data[Scan * 2 + 0]));
  658.                 PRNGCHK(Data,&(Data[Scan * 2 + 1]),sizeof(Data[Scan * 2 + 1]));
  659.                 PRNGCHK(LeftDelayLineArray,&(LeftDelayLineArray[VectorIndex]),
  660.                     sizeof(LeftDelayLineArray[VectorIndex]));
  661.                 PRNGCHK(RightDelayLineArray,&(RightDelayLineArray[VectorIndex]),
  662.                     sizeof(RightDelayLineArray[VectorIndex]));
  663.                 Data[Scan * 2 + 0] = LeftDelayLineArray[VectorIndex];
  664.                 Data[Scan * 2 + 1] = RightDelayLineArray[VectorIndex];
  665.                 /* increment index */
  666.                 VectorIndex = (VectorIndex - 1) & VectorMask;
  667.             }
  668.         Delay->DelayLineIndex = VectorIndex;
  669.     }
  670.  
  671.  
  672. /* apply delay processing to some stuff to mono data */
  673. void                            ApplyDelayLineMono(largefixedsigned* Data, long NumFrames,
  674.                                         DelayLineRec* Delay)
  675.     {
  676.         long                        Scan;
  677.         long                        VectorMask;
  678.         long                        VectorIndex;
  679.         largefixedsigned*    LeftDelayLineArray;
  680.  
  681.         CheckPtrExistence(Data);
  682.         CheckPtrExistence(Delay);
  683.         VectorMask = Delay->DelayLineLength - 1;
  684.         VectorIndex = Delay->DelayLineIndex;
  685.         LeftDelayLineArray = Delay->LeftDelayLineArray;
  686.         for (Scan = 0; Scan < NumFrames; Scan += 1)
  687.             {
  688.                 DelayLineTapRec*    Tap;
  689.  
  690.                 /* clear current output point */
  691.                 LeftDelayLineArray[VectorIndex] = Data[Scan];
  692.                 /* iterate over taps */
  693.                 Tap = Delay->Taps;
  694.                 while (Tap != NIL)
  695.                     {
  696.                         long                            SourceIndex;
  697.                         long                            TargetIndex;
  698.                         largefixedsigned    Temp;
  699.  
  700.                         /* precompute some stuff */
  701.                         SourceIndex = VectorMask & (VectorIndex +  Tap->SourceOffset);
  702.                         TargetIndex = VectorMask & (VectorIndex +  Tap->TargetOffset);
  703.                         PRNGCHK(LeftDelayLineArray,&(LeftDelayLineArray[SourceIndex]),
  704.                             sizeof(LeftDelayLineArray[SourceIndex]));
  705.                         PRNGCHK(LeftDelayLineArray,&(LeftDelayLineArray[TargetIndex]),
  706.                             sizeof(LeftDelayLineArray[TargetIndex]));
  707.                         /* apply transformation */
  708.                         switch (Tap->TapProcessAlgorithm)
  709.                             {
  710.                                 default:
  711.                                     EXECUTE(PRERR(ForceAbort,
  712.                                         "ApplyDelayLineMono:  unknown tap processing algorithm"));
  713.                                     break;
  714.                                 case eTapLeftToLeftNoFilter:
  715.                                 case eTapLeftToMonoNoFilter:
  716.                                 case eTapLeftToRightNoFilter:
  717.                                 case eTapMonoToLeftNoFilter:
  718.                                 case eTapMonoToMonoNoFilter:
  719.                                 case eTapMonoToRightNoFilter:
  720.                                 case eTapRightToLeftNoFilter:
  721.                                 case eTapRightToMonoNoFilter:
  722.                                 case eTapRightToRightNoFilter:
  723.                                     LeftDelayLineArray[TargetIndex] += (largefixedsigned)(
  724.                                         LeftDelayLineArray[SourceIndex] * Tap->Scaling);
  725.                                     break;
  726.                                 case eTapLeftToLeftAverageFilter:
  727.                                 case eTapLeftToMonoAverageFilter:
  728.                                 case eTapLeftToRightAverageFilter:
  729.                                 case eTapMonoToLeftAverageFilter:
  730.                                 case eTapMonoToMonoAverageFilter:
  731.                                 case eTapMonoToRightAverageFilter:
  732.                                 case eTapRightToLeftAverageFilter:
  733.                                 case eTapRightToMonoAverageFilter:
  734.                                 case eTapRightToRightAverageFilter:
  735.                                     Temp = LeftDelayLineArray[SourceIndex];
  736.                                     LeftDelayLineArray[TargetIndex] += (largefixedsigned)(((Temp
  737.                                         + Tap->MovingAverageFilterState) >> 1) * Tap->Scaling);
  738.                                     Tap->MovingAverageFilterState = Temp;
  739.                                     break;
  740.                             }
  741.                         /* do the next one */
  742.                         Tap = Tap->Next;
  743.                     }
  744.                 /* perform data update */
  745.                 PRNGCHK(Data,&(Data[Scan]),sizeof(Data[Scan]));
  746.                 PRNGCHK(LeftDelayLineArray,&(LeftDelayLineArray[VectorIndex]),
  747.                     sizeof(LeftDelayLineArray[VectorIndex]));
  748.                 Data[Scan] = LeftDelayLineArray[VectorIndex];
  749.                 /* increment index */
  750.                 VectorIndex = (VectorIndex - 1) & VectorMask;
  751.             }
  752.         Delay->DelayLineIndex = VectorIndex;
  753.     }
  754.